from celery import shared_task

from datetime import datetime, date, timedelta
from django.utils import timezone
from django.db.models import Avg, Max, Min, Count, Sum
from iClouds.apidev import hash_md5, hash_name, hash_time, has_Random
from MoniterManager.tasks import doMoniterPulsarScreen
from mysqldb import redis as REDIS
from mysqldb import tasks as TASKS
from mysqldb.models import (
    AllinpayMemberList,
    AllinpayHardwareList,
    AllinpayPlaceList,
    AllinpayProgrunList,
    FsygMemberLevel,
    GameLolHonebaoList,
    GameLolHonebaoLogs,
)

import time,json
import logging

logger = logging.getLogger(__name__)


@shared_task
def Q8doProgrunList(pid, data):
    """处理本地上下机推送消息"""

    def has_guid(pid, pcname, uptime):
        """计算上机时间"""
        guid = f"{uptime}{pcname}{pid}"
        return hash_md5(guid)

    def doWriteRedis(pid, dbs):
        """写入缓存"""
        dbs = REDIS.clear_dict(dbs)
        key = f'{pid}--{data.get("client_name")}'
        REDIS.redis_del("workStatus", key)
        REDIS.redis_hash_set("workStatus", key, dbs)

    def has_Member_Level(wbid, name):
        """查询会员等级"""
        try:
            r = FsygMemberLevel.objects.get(wbcode=wbid, name=name)
        except BaseException as err:
            return 1
        else:
            return r.level

    def has_Member_birthday(code):
        """计算会员生日"""
        try:
            b = f"{code[6:10]}-{code[10:12]}-{code[12:14]}"
            return b
        except BaseException as err:
            return None

    def has_Member_gender(code):
        """计算会员性别,使用位运算"""
        try:
            b = int(code[-2])
        except BaseException as err:
            return 0
        else:
            if (b & 1) == 0:
                # 偶数
                return 0
            else:
                # 奇数
                return 1

    def to_Count_Week(wbid, cardid):
        """统计每周会员次数"""
        week = date.today().weekday()
        sd = date.today() - timedelta(days=week)
        ed = sd + timedelta(days=7)
        c = AllinpayProgrunList.objects.filter(
            pid=wbid, carid=cardid, on_day__range=(sd, ed)
        ).aggregate(cishu=Count("id"))
        return c.get("cishu", 0)



    """开始任务"""
    if data.get("UID"):  # 会员下机
        # 创建公共数据
        hostname,area,midcode = "","",""
        # 查找在线记录
        c = int(time.mktime(time.strptime(data.get("start_time"), "%Y-%m-%d %H:%M:%S")))        
        guid = has_guid(pid, data.get("client_name"), str(c))
        try:
            res = AllinpayProgrunList.objects.get(guid=guid)
        except BaseException as err:
            logger.warn(f"[cqbar] [{pid}] 下机查询在线记录失败 {err} {data}")
            # raise ValueError(f"[cqbar] 查询在线记录失败 {err}")
        else:
            res.message_type = "downmachine"
            if not res.computer_name == data.get("client_name"):
                res.bem = f'换机 {res.computer_name} -> {data.get("client_name")}'
                res.computer_name = data.get("client_name")
                res.computer_area = data.get("client_area")
            res.amount = int(float(data.get("amount")) * 100)
            res.down_day = datetime.strptime(
                data.get("end_time"), "%Y-%m-%d %H:%M:%S"
            ).date()
            res.down_time = datetime.strptime(data.get("end_time"), "%Y-%m-%d %H:%M:%S")
            res.save()
            hostname = res.computer_name
            area = res.computer_area
            midcode = res.carid

        # 检查会员
        try:
            v = AllinpayMemberList.objects.get(idcode=midcode, pid=pid)
        except BaseException as err:
            logger.warn(f"[cqbar] [{pid}]  下机查询会员失败 {err} {data}")
            # raise ValueError(f"[cqbar] 查询会员失败 {err}")
        else:
            # 计算统计数据
            v.accummoney = v.accummoney + int(float(data.get("amount")) * 100)  # 累计消费金额 (分)
            v.accumtime = v.accumtime + int(data.get("timelen"))  # 累计上机时长 (分钟)
            v.overage = int(float(data.get("balance")) * 100)  # 当前余额 (分)
            v.save()

        if hostname:
            # 创建数据
            dbs = {
                "status": 2,  # 终端状态 0维修，1上机中，2待清洁，3待机中
                "localhost": hostname,  # 终端机号
                "group": area,
                "ipaddr": None,
                "mask": None,
                "gateway": None,
                "currenttime": data.get("end_time"),
            }
            # 写入缓存
            doWriteRedis(pid, dbs)
            # # 创建下机清理
            from fsygManager.tasks import CreateCallmeClearReqsn

            callme = CreateCallmeClearReqsn(pid, hostname)
            # # 发送消息队列pulsar
            r = doMoniterPulsarScreen(f"{pid}", dbs)
    else:  # 会员上机
        # 检查会员
        v, faq = AllinpayMemberList.objects.update_or_create(
            defaults={
                "name": hash_name(data.get("real_name")),                
                "lasttime": hash_time(int(data.get("upmachine_time"))),
                "level": data.get("cn_account_level"),
                "hash": data.get("paper_id")
            },
            idcode=hash_md5(data.get("UserID").upper()),
            pid=pid,
        )
        if faq:
            v.creattime = hash_time(int(data.get("create_time")))
            v.gender = has_Member_gender(data.get("UserID"))
            v.birthday = has_Member_birthday(data.get("UserID"))
            v.overage = 0
            v.reward = 0
            v.integral = 0
            v.accummoney = 0
            v.accumtime = 0
            v.save()
            logger.info(f'[cqbar] [{pid}] 创建新会员 {v.id}')
            
        # 检查终端
        p, fap = AllinpayHardwareList.objects.update_or_create(
            defaults={"lasttime": v.lasttime,"ipaddr": data.get("ClientIP"), "area": data.get("client_area")},
            pcname=data.get("client_name"),
            pid=pid,
        )
        if fap:
            p.status = 1
            p.save() 
            
        # 上机记录
        guid = has_guid(pid, p.pcname, data.get("upmachine_time"))
        r, far = AllinpayProgrunList.objects.update_or_create(
            defaults={
                "message_type": "upmachine",
                "carid": v.idcode,
                "computer_name": p.pcname,
                "computer_area": p.area,
                "pid": pid,
                "on_day": v.lasttime.date(),
                "on_time": v.lasttime,
            },
            guid=guid,
        )

        # 统计数据
        try:
            dc = to_Count_Week(data.get("wb_id"), data.get("card_id")) + 1
        except BaseException as err:
            dc = 1
        dbs = {
            "status": 1,
            "localhost": p.pcname,  # 终端机号
            "group": p.area,
            "ipaddr": p.ipaddr,
            "mask": "",
            "gateway": "",
            "currenttime": v.lasttime.strftime("%Y-%m-%d %H:%M:%S"),
            "hash": v.idcode,
            "guid": guid,
            "gender": v.gender,  # random.choice(range(2)),
            "level": has_Member_Level(pid, data.get("cn_account_level")),
            "member": {
                "name": v.name,
                "code": "",
                "hash": v.idcode,
                "phone": v.phone,
                "birthday": v.birthday,
                "gender": v.gender,
                "openid": v.openid,
                "registtime": str(v.creattime),
                "lasttime": str(v.lasttime),
                "level": v.level,
                "overage": v.overage,
                "reward": v.reward,
                "integral": v.integral,
                "accummoney": v.accummoney,
                "accumtime": v.accumtime,
            },
            "Count": {
                "money": v.accummoney,
                "domoney": 0,
                "timelong": v.accumtime,
                "dolong": 0,
                "week": dc,
            },
        }
        # # 写缓存
        doWriteRedis(pid, dbs)
        # # 发送消息队列pulsar
        r = doMoniterPulsarScreen(f"{pid}", dbs)
    return {"rescode": 200, "resmsg": "success","currenttime":timezone.now()}


@shared_task
def Q8doGameXiaguList(pid, data):
    """处理游戏数据 召唤师峡谷"""
    try:
        # data = eval(data)
        data = json.loads(data)
    except BaseException as err:
        logger.warn(f"[Games] [lol] [{pid}] 解析数据失败 {err}")
        raise ValueError(f"[Games] [lol] 解析数据失败 {err}")   
    try:
        mid = AllinpayMemberList.objects.get(idcode=hash_md5(data.get("UserID").upper()), pid=pid)
    except BaseException as err:
        logger.warn(f"[Games] [lol] [{pid}] 查询会员失败 {err} {data}")
        raise ValueError(f"[Games] [lol] 查询会员失败 {err}")        
    # mid = 1
    # 处理数据
    sess = {}
    sess["pid"] = pid
    sess["mid"] = mid.id
    sess["computername"] = data.get("jUserInfo_Json",{}).get("ComputerName") # 机号    
    sess["summonerid"] =   data.get("summonerId") # 游戏账号ID
    sess["summonername"] = data.get("summonerName") # 召唤师名
    sess["area_cname"] =  data.get("jUserInfo_Json",{}).get("area_cname") # 大区信息
    sess["tier"] =        data.get("jUserInfo_Json",{}).get("Tier") # 段位等级
    sess["cn_champion"] = data.get("battle_ratio_json",{}).get("cn_Champion") # 英雄名称
    sess["cn_gamemode"] = data.get("battle_ratio_json",{}).get("cn_GameMode") # 游戏模式
    sess["cn_gametype"] = data.get("battle_ratio_json",{}).get("cn_GameType") # 游戏类型    
    sess["win"] =         data.get("battle_ratio_json",{}).get("Win") # 1 胜利；2 失败
    sess["winpoint"] =    data.get("battle_ratio_json",{}).get("WinPoint") # 胜点    
    sess["start_time"]=   data.get("battle_ratio_json",{}).get("start_time") # 对局开始时间
    sess["stop_time"] =   data.get("battle_ratio_json",{}).get("stop_time")    # 对局结束时间
    sess["lol_money"] =   data.get("battle_ratio_json",{}).get("lol_money") # 奖励金额基数
    sess["firstwin"] =    data.get("battle_ratio_json",{}).get("WB_FirstWinBonus_Multiple") # 首胜奖励倍数
    sess["seat_ratio"] = data.get("battle_ratio_json",{}).get("seat_ratio") # 座位系数
    sess["tier_ratio"] = data.get("battle_ratio_json",{}).get("tier_ratio") # 段位系数
    sess["time_ratio"] = data.get("battle_ratio_json",{}).get("time_ratio") # 时间系数
    sess["area_ratio"] = data.get("battle_ratio_json",{}).get("area_ratio") # 大区系数
    sess["type_ratio"] = data.get("battle_ratio_json",{}).get("type_ratio") # 赛制系数
    sess["wx_money"] = data.get("battle_ratio_json",{}).get("wx_money") # 红包金额 = 奖励金额*系数   
    sess["status"] = 0
    sess["currentime"] = timezone.now()
    sess["code"] = has_Random()
    # sess = REDIS.clear_dict(sess)
    # 查询门店
    try:
        place = AllinpayPlaceList.objects.get(id=pid)
    except BaseException as err:
        p_name = ""
    else:
        p_name = place.basename        
    try:
        r = GameLolHonebaoList(**sess)
        r.save()
    except BaseException as err:
        logger.warn(f"[Games] [lol] [{pid}] 创建记录失败 {err} {data}")
    else:
        # 写入成就记录
        try:
            lolog = [GameLolHonebaoLogs(parent=r.id, **{key.lower(): value for key, value in args.items()}) for args in data.get("battle_ratio_json",{}).get("data",[])]
            GameLolHonebaoLogs.objects.bulk_create(lolog)
        except BaseException as err:
            logger.warn(f"[Games] [lol] 创建对局数据失败 {err}")   
        # 发送模板消息给会员
        if mid.openid:
            s = TASKS.WeAppsOpenidformSend(mid.openid,f"https://we.hs6686.com/#/lol?id={r.id}", "提现申请提交成功通知",[p_name, r.wx_money,mid.name,r.currentime.strftime("%Y年%m月%d日 %H:%M:%S")])
    return {"rescode": 200, "resmsg": "success","currenttime":timezone.now()}    